package com.hhuhh.smarthome.socket.udp;

import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.util.HashMap;
import java.util.Map;

import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.core.session.IoSession;

import com.hhuhh.smarthome.socket.AcceptorCallback;
import com.hhuhh.smarthome.socket.IoConstants;
import com.hhuhh.smarthome.socket.SocketDataRSA;
import com.hhuhh.smarthome.socket.model.ResponseDataType;
import com.hhuhh.smarthome.socket.model.SimpleData;

/**
 * @author: John zhang
 * @version: 0.1
 */
public class UdpClientIoHandler extends IoHandlerAdapter implements SocketDataRSA {

	public static Map<String, AcceptorCallback<? extends ResponseDataType>> acceptors = new HashMap<String, AcceptorCallback<? extends ResponseDataType>>();

	public static final String SERVER_PUBLICKEY_ATTR_KEY = "serverPublicKey";

	private PublicKey serverPubKey; // 服务端公钥
	private PublicKey pubKey; // 客户端公钥
	private PrivateKey priKey; // 客户端私钥
	private boolean useRSA; // 是否使用RSA加密

	public void messageReceived(IoSession session, Object message) throws Exception {
		String msg = new String( (byte[]) message );
		System.out.println( msg );
		
		/*if (message instanceof String) {
			StringHandlerAtMessage(session, (String) message);
		} else if (message instanceof IoBuffer) {

		}*/
	}

	// 发送消息异常
	public void exceptionCaught(IoSession session, Throwable cause) {
		session.close(true);
	}

	@Override
	public void sessionIdle(IoSession session, IdleStatus status) throws Exception {
		final String action = (String) session.getAttribute(IoConstants.REQUEST_ACTION_KEY);
		AcceptorCallback<?> callback = acceptors.get(action);
		if (callback != null) {
			if (IoConstants.DEBUG) {
				System.out.println("服务端响应超时..");
			}
			callback.readerOrWriterIdleHandler();
		}
		session.close(true);
	}

	@Override
	public void sessionClosed(IoSession session) throws Exception {
		System.out.println("session被关闭.");
		serverPubKey = null;
		pubKey = null;
		priKey = null;
	}

	/**
	 * 是否使用RSA对数据进行加密/解密
	 * 
	 * @param val
	 */
	public void setUseRSA(boolean val) {
		setUseRSA(val, null, null);
	}

	/**
	 * 是否使用RSA对数据进行加密/解密, 如果启用RSA加密, 则需要设置私钥与公钥, 否则会抛出异常
	 * 
	 * @param val
	 *            是否启用
	 * @param priKey
	 *            客户端私钥
	 * @param pubKey
	 *            客户端公钥
	 */
	public void setUseRSA(boolean val, PublicKey pubKey, PrivateKey priKey) {
		if (val && (priKey == null || pubKey == null)) {
			throw new IllegalArgumentException("If you use RSA encrypt or decrypt datas, please invoked setPrivateKey() and setPublicKey()");
		}
		this.useRSA = val;
		this.priKey = priKey;
		this.pubKey = pubKey;
	}

	public boolean isUseRSA() {
		return useRSA;
	}

	/**
	 * 添加消息接收回调函数
	 * 
	 * @param key
	 * @param callback
	 */
	public void addCallback(String key, AcceptorCallback<? extends ResponseDataType> callback) {
		if (acceptors == null) {
			acceptors = new HashMap<String, AcceptorCallback<? extends ResponseDataType>>();
		}

		@SuppressWarnings("unused")
		AcceptorCallback<?> oldAcceptor = acceptors.put(key, callback);
		oldAcceptor = null;
	}

	@Override
	public RSAPublicKey getClientPubKey() {
		return (RSAPublicKey) pubKey;
	}

	@Override
	public RSAPrivateKey getPriKey() {
		return (RSAPrivateKey) priKey;
	}

	@Override
	public RSAPublicKey getServerPubKey() {
		return (RSAPublicKey) serverPubKey;
	}

	@Override
	public void sessionOpened(IoSession session) throws Exception {
		System.out.println( "session opened , " + session.getRemoteAddress() );
	}

}